// <!-- 组件: zj-file 文件 选择&展示&上传 -->
// ==================== 参数 ====================
// ※ url ==> 双向绑定, 文件地址 (默认: [])
// ※ name ==> 双向绑定, 文件名 (默认: [])
// ※ model ==> 双向绑定时父组件的键名 (默认: [])
// ※ modelKey ==> 双向绑定时子组件对应键名 (默认: [])
// ※ baseUrl ==> 前缀地址 (默认: $app.baseUrl)
// ※ label ==> 上传按钮显示内容 (默认: '请添加附件')
// ※ label_tip ==> 上传按钮右侧提示内容, 不传不现实 (默认: null)
// ※ maxlength ==> 最大允许上传个数, 不传则默认无限制 (默认: 0)
// ※ fileType ==> 上传文件类型, 不传则默认全部类型 (默认: [])
// ※ isEdit ==> 是否可编辑 (默认: true)
// ==================== 事件 ====================
// ※ bind:model="model(e)" ==> 双向绑定
// ※ bind:uploadEnd(e) ==> 上传结束后触发
//      e.detail = {
//        result: success/fail/complete, // 完成状态(全部成功/全部失败/有成功有失败)
//        successUp: 0, // 当前上传成功个数
//        failUp: 0 // 当前上传失败个数
//        other: null // 调用'upload'方法时传递进来的参数
//      }
// ==================== 方法 ====================
// ※ upload([model], [api], [other]) ==> 上传文件

const $app = getApp()
Component({
  properties: {
    url: { // 文件路径
      type: Array
    },
    name: { // 文件名
      type: Array
    },
    model: { // 双向绑定时父组件的键名
      type: Array,
      value: []
    },
    modelKey: { // 双向绑定时子组件对应键名
      type: Array,
      value: []
    },
    baseUrl: {
      type: String,
      value: $app.baseUrl
    },
    label: { // 上传按钮显示内容
      type: String,
      optionalTypes: [String, Number],
      value: '添加附件'
    },
    label_tip: { // 上传按钮右侧提示内容
      type: String,
      optionalTypes: [String, Number],
      value: ''
    },
    maxlength: { // 最大允许上传个数, 不传则默认无限制
      type: Number,
      value: 0
    },
    fileType: { // 上传文件类型, 不传则默认全部类型
      type: Array,
      value: []
    },
    isEdit: { // 不可添加 展示文件
      type: Boolean,
      optionalTypes: [String, Number, Boolean],
      value: true
    }
  },
  data: {
    url_child: [], // 文件路径, 与'url'双向绑定使用(注: 不能直接改变'url', 否则监听赋值会变成死循环)
    files: [], // 文件集
    uploadNum: 0, // 上传总数
    successUp: 0, // 当前上传成功个数
    failUp: 0, // 当前上传失败个数
    completeUp: 0, // 当前上传完成个数 监听
    other: null // 调用'upload'方法时传递进来的参数
  },
  observers: {
    // ========== 监听'url', 双向绑定 ==========
    'url': function (url) {
      const url_str = url.toString()
      const url_child_str = this.data.url_child.toString()
      if (url_str !== url_child_str) {
        this.setData({
          url_child: url,
          files: url
        })
      }
    },
    'url_child': function (url_child) {
      const e = {
        url: this.data.url_child,
        name: this.properties.name,
        model: this.properties.model,
        modelKey: this.properties.modelKey,
      }
      this.triggerEvent('model', e)
    },
    // ========== 监听'当前上传完成个数', 判断上传时间是否完成 ==========
    'completeUp': function (completeUp) {
      const uploadNum = this.data.uploadNum
      const successUp = this.data.successUp
      const failUp = this.data.failUp
      const text = `已上传${successUp}个`
      $app.$common.openLoading(text, 'loading')
      if (completeUp && completeUp === uploadNum) {
        const e = {
          result: null,
          failUp: failUp,
          successUp: successUp,
          other: this.data.other
        }
        if (successUp === uploadNum) {
          e.result = 'success'
        } else if (failUp === uploadNum) {
          e.result = 'fail'
        } else {
          e.result = 'complete'
        }
        this.triggerEvent('uploadEnd', e)

      }
    }
  },
  methods: {
    // ========== 新增(选择) ==========
    add () {
      const maxlength = this.properties.maxlength
      const fileslength = this.data.files.length
      if (maxlength && fileslength >= maxlength) return
      wx.chooseMessageFile({
        count: 10,
        // type: 'file',
        success: (res) => {
          let newfiles = res.tempFiles || []
          if (maxlength && newfiles.length + fileslength > maxlength) {
            newfiles.length = maxlength - fileslength
          }
          let url_child = Array.from(this.data.url_child)
          let name = Array.from(this.properties.name)
          let files = Array.from(this.data.files)
          newfiles.forEach(b => {
            url_child.push(0)
            name.push(b.name)
            files.push(b.path)
          })
          this.setData({ url_child, name, files })
        }
      })
    },
    // ========== 删除 ==========
    del (e) {
      let index = e.currentTarget.dataset.index // 选中当前下标
      let url_child = Array.from(this.data.url_child) // 文件路径
      let name = Array.from(this.properties.name) // 文件名
      let files = Array.from(this.data.files) // 文件集
      url_child.splice(index, 1)
      name.splice(index, 1)
      files.splice(index, 1)
      this.setData({ url_child, name, files })
    },
    // ======= 判断是否是图片类型 =====
    isAssetTypeAnImage(ext) {
      return [
      '.png', '.jpg', '.jpeg', '.bmp', '.gif', '.webp', '.psd', '.svg', '.tif'].
      indexOf(ext.toLowerCase()) !== -1;
    },
    // ========== 下载(其实无法下载, 仅可以查看。若想将文件保存, 则在打开后点击右上角分享) ==========
    download (e) {
      let pathName = this.properties.name[e.currentTarget.dataset.index]
      const url = this.properties.baseUrl + e.currentTarget.dataset.path // 地址
      const suffix = e.currentTarget.dataset.path
      const newsuff = suffix.substring(suffix.lastIndexOf('.'), suffix.length) // 后缀
      if (this.isAssetTypeAnImage(newsuff)) { // 判断是否是图片类型
        this.onSaveToPhone(url)
        console.log('图片格式')
      } else {
        $app.$common.openLoading('加载文件中') // 打开加载
        wx.downloadFile({
          url: url,
          success (res) {
            const fs = wx.getFileSystemManager()
            fs.saveFile({
              tempFilePath: res.tempFilePath,
              filePath: wx.env.USER_DATA_PATH + '/' + pathName,
              success: (res1) => {
                wx.openDocument({
                  filePath: res1.savedFilePath,
                  showMenu: true,
                  success: (res2) => {
                    $app.$common.closeLoading() // 关闭加载
                  },
                  fail: (res2) =>{
                    console.log('zj-file 打开失败', res2)
                    $app.$common.closeLoading() // 关闭加载
                    $app.$common.message('该文件不支持打开')
                  }
                })
              },
              fail: (res1) =>{
                console.log('zj-file 存储失败', res1)
                $app.$common.closeLoading() // 关闭加载
                $app.$common.message(res1.errMsg)
              }
            })
          },
          fail (res) { // 下载失败
            console.log('zj-file 下载失败', res)
            $app.$common.closeLoading() // 关闭加载
            $app.$common.message(res.errMsg)
          }
        })
      }
    },
    onSaveToPhone (url) {
      this.getSetting().then((res) => {
        // 判断用户是否授权了保存到本地的权限
        if (!res.authSetting['scope.writePhotosAlbum']) {
          this.authorize().then(() => {
            console.log('授权通过')
            this.savedownloadFile(url)
            wx.downloadFile({
              url: url,
              success: (res) => {
                console.log('downloadfile', res)
              }
            })
          }).catch(() => {
            this.onOpenSetting(url)
          })
        } else {
          console.log('授权通过')
          this.savedownloadFile(url)
        }
      })
    },
    // 弹出授权界面
    onOpenSetting (url) {
      wx.showModal({
        title: '检测到您没有打开保存到相册的权限，是否前往设置打开？',
        success: (res) => {
          if (res.confirm) {
            console.log('用户点击确定')
            wx.openSetting({
              success:(res) => {
                if (!res.authSetting['scope.writePhotosAlbum']) {
                  wx.showToast({
                    title: '您未授权',
                    icon: 'none',
                    duration: 1500
                  })
                } else {// 接受授权
                  this.onSaveToPhone(url) // 接受授权后保存图片
                }
              }
            })        
          } else if (res.cancel) {
            console.log('用户点击取消')
          }
        }
      })
    },
    // 获取用户已经授予了哪些权限
    getSetting() {
      return new Promise((resolve, reject) => {
        wx.getSetting({
          success: res => {
            resolve(res)
          }
        })
      })
    },
    // 发起首次授权请求
    authorize() {
      return new Promise((resolve, reject) => {
        wx.authorize({
          scope: 'scope.writePhotosAlbum',
          success: () => {
            resolve()
          },
          fail: res => { //这里是用户拒绝授权后的回调
            reject()
          }
        })
      })
    },
    // 下载图片
    savedownloadFile (url) {
      wx.downloadFile({
        url: url,
        success: (res) => {
          console.log('downloadfile', res)
          wx.saveImageToPhotosAlbum({
            filePath: res.tempFilePath,
            success: (res) => {
              wx.showToast({
                title: '保存到手机相册',
                duration: 1000,
              })
            }
          })
        }
      })
    },
    // ========== 上传 ==========
    // 注: 'other'仅做传递使用
    upload (model, api, other) {
      this.setData({
        other: other, // 传递参数
        uploadNum: 0, successUp: 0, failUp: 0, completeUp: 0 // 初始化上传相关数据
      })
      const url = this.properties.baseUrl + model + '/' + api // 地址
      let files = []
      this.data.url_child.forEach((b, i) => {
        b === 0 && files.push({ i: i, path: this.data.files[i] })
      })
      if (files.length) {
        this.setData({ uploadNum: files.length }) // 上传总数
        files.forEach(b => { this.uploadfile(url, b) }) // 调用上传文件方法
      } else {
        const e = {
          result: 'success',
          failUp: 0,
          successUp: 0,
          other: other
        }
        this.triggerEvent('uploadEnd', e)
      }
    },
    uploadfile (url, b) { // 上传方法
      wx.uploadFile({
        url: url,
        filePath: b.path,
        name: 'file',
        header: { 
          'Content-Type': 'multipart/form-data',
          'accept': 'application/json'
        },
        success: (e) => {
          let data = JSON.parse(e.data).data || ''
          this.setData({
            [`url_child[${b.i}]`]: data,
            // [`files[${b.i}]`]: this.properties.baseUrl + data,
            successUp: this.data.successUp + 1 // 成功+1
          })
        },
        fail: (e) => {
          this.setData({ failUp: this.data.failUp + 1 }) // 失败+1
        },
        complete: (e) =>{
          this.setData({ completeUp: this.data.completeUp + 1 }) // 完成+1
        }
      })
    }
  }
})
